package org.waigua.moka.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.log4j.Logger;
import org.waigua.moka.dto.ApiDto;
import org.waigua.moka.dto.ContentApiDto;
import org.waigua.moka.dto.InnerApiDto;
import org.waigua.moka.service.HttpApiService;
import org.waigua.moka.util.UnicodeUtil;

import com.google.gson.Gson;

public class HttpApiServiceImpl implements HttpApiService
{
	protected Logger log = Logger.getLogger(getClass());

	@SuppressWarnings("unchecked")
	protected Map<String, ?> commonApi(InnerApiDto apiDto) throws HttpException, IOException
	{

		HttpClient client = new HttpClient();
		String url = "http://" + apiDto.getHost() + "/" + apiDto.getTarget() + "?do=" + apiDto.getAction() + "&v="
				+ apiDto.getV() + "&phpp=" + apiDto.getPhpp() + "&phpl=" + apiDto.getPhpl() + "&pvc=" + apiDto.getPvc()
				+ "&pvb=" + apiDto.getPvb();
		log.info("请求地址" + url + ";body=" + apiDto.getBody());
		PostMethod post = new PostMethod(url);
		try
		{
			for (String key : apiDto.getHeaderMap().keySet())
			{
				post.setRequestHeader(key, apiDto.getHeaderMap().get(key));
			}
			if (0 != apiDto.getContentLength())
			{
				RequestEntity requestEntity = new StringRequestEntity(apiDto.getBody(), apiDto.getContentType(),
						apiDto.getCharSet());
				post.setRequestEntity(requestEntity);
			}
			int status = client.executeMethod(post);
			if (status != 200)
			{
				log.error("请求响应状态错误status=" + status + ";" + post.getResponseBodyAsString());
				throw new HttpException("status = " + status);
			}
			String result = readGzip(post);
			result = UnicodeUtil.unicodeToString(result);
			Gson gson = new Gson();
			Map<String, ?> map = gson.fromJson(result, HashMap.class);
			if (map == null)
			{
				throw new IOException("响应结果转换JSON失败,result=" + result);
			}
			BigDecimal apiStatus = new BigDecimal(String.valueOf(map.get("status")));
			if (apiStatus.compareTo(BigDecimal.ONE) != 0)
			{
				throw new IllegalStateException("响应结果状态不为1,result=" + result);
			}
			if ((Map<String, ?>) map.get("data") == null)
			{
				throw new HttpException("响应结果data不为MAP,result=" + result);
			}
			return (Map<String, ?>) map.get("data");
		}
		finally
		{
			post.releaseConnection();
		}
	}

	protected static String readGzip(HttpMethod method) throws IOException
	{
		String acceptEncoding = "";
		if (method.getResponseHeader("Content-Encoding") != null)
			acceptEncoding = method.getResponseHeader("Content-Encoding").getValue();
		StringBuffer sb = new StringBuffer();
		if (acceptEncoding.toLowerCase().indexOf("gzip") > -1)
		{

			InputStream is = method.getResponseBodyAsStream();
			try
			{
				GZIPInputStream gzin = new GZIPInputStream(is);
				InputStreamReader isr = new InputStreamReader(gzin);
				java.io.BufferedReader br = new java.io.BufferedReader(isr);
				String tempbf;
				while ((tempbf = br.readLine()) != null)
				{
					sb.append(tempbf);
					sb.append("\r\n");
				}
				isr.close();
				gzin.close();
			}
			finally
			{
				is.close();
			}
		}
		else
		{
			InputStreamReader isr = new InputStreamReader(method.getResponseBodyAsStream());
			try
			{
				java.io.BufferedReader br = new java.io.BufferedReader(isr);
				String tempbf;
				while ((tempbf = br.readLine()) != null)
				{
					sb.append(tempbf);
					sb.append("\r\n");
				}
			}
			finally
			{
				isr.close();
			}
		}
		return sb.toString();
	}

	public Map<String, ?> getUserinfo(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("user.php");
		innerApiDto.setAction("GetUserinfo");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> getThieves(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("arena.php");
		innerApiDto.setAction("GetThieves");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> thievesFight(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "UserThievesId");
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("arena.php");
		innerApiDto.setAction("ThievesFight");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> getUserLegion(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("legion.php");
		innerApiDto.setAction("GetUserLegion");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> getUserMapStages(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("mapstage.php");
		innerApiDto.setAction("GetUserMapStages");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> editUserMapStages(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "isManual", "MapStageDetailId");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("mapstage.php");
		contentApiDto.setAction("EditUserMapStages");
		return commonApi(contentApiDto);
	}

	void commonValidateContent(ApiDto apiDto, String... params)
	{
		if (!(apiDto instanceof ContentApiDto))
		{
			throw new IllegalArgumentException("缺少提交内容");
		}
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		if (contentApiDto.getParams() == null)
		{
			throw new IllegalArgumentException("缺少提交内容");
		}
		for (String param : params)
		{
			if (!contentApiDto.getParams().containsKey(param))
			{
				throw new IllegalArgumentException("缺少提交内容" + param);
			}
		}
	}

	@Override
	public Map<String, ?> showMaze(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "MapStageId");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("maze.php");
		contentApiDto.setAction("Show");
		return commonApi(contentApiDto);
	}
	
	@Override
	public Map<String, ?> mazeInfo(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "Layer", "MapStageId");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("maze.php");
		contentApiDto.setAction("Info");
		return commonApi(contentApiDto);
	}
	
	@Override
	public Map<String, ?> mazeBattle(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "OpenCardChip", "MapStageId", "ItemIndex", "manual", "Layer");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("maze.php");
		contentApiDto.setAction("Battle");
		return commonApi(contentApiDto);
	}
	
	@Override
	public Map<String, ?> getChips(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("chip.php");
		innerApiDto.setAction("GetUserChip");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> getBoss(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("boss.php");
		innerApiDto.setAction("GetBoss");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> fightBoss(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("boss.php");
		innerApiDto.setAction("Fight");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> resetMaze(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "MapStageId");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("maze.php");
		contentApiDto.setAction("Reset");
		return commonApi(contentApiDto);
	}

	@Override
	public Map<String, ?> getCompetitors(ApiDto apiDto) throws HttpException, IOException
	{
		InnerApiDto innerApiDto = (InnerApiDto) apiDto;
		innerApiDto.setTarget("arena.php");
		innerApiDto.setAction("GetCompetitors");
		return commonApi(innerApiDto);
	}

	@Override
	public Map<String, ?> freeFight(ApiDto apiDto) throws HttpException, IOException
	{
		commonValidateContent(apiDto, "isManual", "Competitor");
		ContentApiDto contentApiDto = (ContentApiDto) apiDto;
		contentApiDto.setTarget("arena.php");
		contentApiDto.setAction("FreeFight");
		return commonApi(contentApiDto);
	}

}
